New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fixes #23851: first auto-bond implementation #439
Conversation
Do not merge! This patch has not been tested yet. Can an existing organization member please verify this patch? |
Issues: #23851 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Thomas-Gelf: Thanks, looks good. Do you mind adding a couple of tests for this?
app/models/setting/discovered.rb
Outdated
@@ -66,6 +67,10 @@ def self.discovery_hostname_fact_array | |||
from_array Setting['discovery_hostname'] | |||
end | |||
|
|||
def self.discovery_auto_bond? | |||
Foreman::Cast.to_bool(Setting['discovery_auto_bond']) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this really needed? I believe the value should already be a boolean.
In addition, this is not used anywhere.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think so, just added it as it's being done the same way the line below 😆
@@ -1,9 +1,12 @@ | |||
require 'foreman_discovery/lldp_neighbors' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should not be necessary. Rails does auto loading pretty well. Let's remove this.
You might want to move the library to app/services as well (instead of lib/foreman_discovery/).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It drove me mad to figure out what to place where, as I faced quite some inconsistencies. Well, at least I haven't been able to really grasp the rules. No wonder Ruby projects fire an such an immense amount of stat-calls.
I placed this code in a separate class to make it easier to test in an isolated way. Just, I failed to run the tests, gave some rake test:foreman_discovery examples triggered from the foreman base directory a try, but nothing happened.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@timogoebel: any helpful hint on how to kick the test run would be greatly appreciated!
neighbors.set name, properties | ||
end | ||
|
||
return neighbors |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: superfluous return
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed.
) | ||
|
||
bond.save! | ||
host.interfaces.push bond |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: This needs brackets...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The call to push? Do you have a brackets-everywhere policy?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(because then there would be more)
list.push name if neighbor['PVID'] == interface['PVID'] | ||
end | ||
|
||
list.size > 1 ? list : nil |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit:
list.empty? ? nil : list
or
return if list.empty?
list
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure... I had the second one first, but I hate it to read code where it's not immediately obvious that nil/null must be expected. And what's ugly about this is that it's not list.empty?
- only results with more than one entry are returned, if there is only one peer
it should return nil
.
I changed it to read:
return if list.size < 2
list
This way it's more obvious that at least two are required for a valid candidate.
Cheers,
Thomas
015ebbd
to
43c7b77
Compare
43c7b77
to
2f33af8
Compare
LldpNeighbors is covered, HostConverter will follow |
NB: I tried to address all of the above, just the question related to brackets still stands |
|
We don't have a policy for that, but I'd prefer brackets everywhere except when the method is called without any arguments. |
test/unit/lldp_neighbors_test.rb
Outdated
end | ||
|
||
test "#list_by_pvid gives an empty Hash without LLDP facts" do | ||
assert_equal Hash({}), simple_facts.list_by_pvid |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is the only case were i'd call assert_equal
with brackets. Please omit the Hash()
everywhere, it's not good ruby style.
test/unit/lldp_neighbors_test.rb
Outdated
end | ||
|
||
def lldp_facts | ||
neighbors'facts_with_lldp' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: missing whitespace
test/unit/lldp_neighbors_test.rb
Outdated
test "#list_by_pvid supports multiple PVIDs" do | ||
assert_equal Hash('182' => %w(eth2), '184' => %w(eth1)), lldp_facts.list_by_pvid | ||
end | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the methods below can be private, a better (or modern) way to write this would be using let
. But this is fine as well.
context 'with facts' do
let(:facts) { some code } # acts as a lazy accessor
test 'abc' do
assert facts
end
end
c7168ab
to
f3911c4
Compare
Also extended host_discovery_test:
|
f3911c4
to
79deb6a
Compare
There is one more:
|
bc4ded0
to
d208bd6
Compare
@timogoebel: tests look good to me, please let me know in case you need more |
ok to test |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM.
Don't blame |
I checked this out. Making the changes in memory is actually pretty easy. My naive approach looks like this: diff --git a/app/services/foreman_discovery/host_converter.rb b/app/services/foreman_discovery/host_converter.rb
index bcb1c05..25fa91e 100644
--- a/app/services/foreman_discovery/host_converter.rb
+++ b/app/services/foreman_discovery/host_converter.rb
@@ -33,26 +33,19 @@ class ForemanDiscovery::HostConverter
ip = primary.ip
name = primary.name
- primary.update(
- :primary => false,
- :provision => false,
- :managed => false,
- :name => nil,
- :ip => nil
- )
+ primary.name = nil
+ primary.ip = nil
+ primary.provision = false
+ primary.primary = false
- bond = Nic::Bond.create(
- :identifier => "bond0",
- :attached_devices => neighbors,
- :primary => true,
- :provision => true,
- :name => name,
- :ip => ip,
- :host => host
+ bond = host.interfaces.build(
+ type: 'Nic::Bond',
+ identifier: 'bond0',
+ primary: true,
+ provision: true,
+ name: name,
+ ip: ip
)
-
- bond.save!
- host.interfaces.push(bond)
end
def self.set_build_clean_facts(host) This issue now is, that the primary interface cannot be found as rails thinks the relation is |
@Thomas-Gelf: I like adding the idea of adding this to the fact parser so this code runs when the host is saved to the database. But I don't think it makes a lot of sense in core as the fact parser in core should just provide the data from a system so it can be displayed in Foreman's UI. In discovery we need this before provisioning happens. The fact parser prepares the host for proper provisioning. @lzap, what do you think? |
Overriding our parser is the best idea IMHO so far. :) |
8715fb9
to
f50e810
Compare
Update: I gave the |
Hint: my attempt with the |
71aaa6e
to
2a577f1
Compare
Rebased and fixed mac address setting |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok looks better but I want you to move the eventually_make_bond method somewhere else please.
app/models/host/discovered.rb
Outdated
@@ -143,6 +143,7 @@ def populate_discovery_fields_from_facts(facts) | |||
self.discovery_attribute_set = DiscoveryAttributeSet.where(:host_id => id).first_or_create | |||
self.discovery_attribute_set.update_attributes(import_from_facts) | |||
# set additional discovery attributes | |||
::ForemanDiscovery::HostConverter.eventually_make_bond(self) if Setting[:discovery_auto_bond] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This place is better but the code does not belong into HostConverter.
@@ -19,6 +19,43 @@ def self.to_managed(original_host, set_managed = true, set_build = true, added_a | |||
host | |||
end | |||
|
|||
def self.eventually_make_bond(host) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you move this method out of HostConverter into LldpNeighbors or somewhere else? I suggest creating a "post processing framework":
- ForemanDiscovery::ImportHookService - a simple registry of hooks
- ForemanDiscovery::ImportHook - base class for processor - keep it simple
after_populate(host, facts)
as the only method for now - ForemanDiscovery::ImportHooks::LldpNeighbor - implementation - move this method there
Optionally break method populate_discovery_fields_from_facts
into three other separate hooks: DiscoveryAttribute, SubnetAndTaxonomy and LockTemplates. I can do this later if you don't want to touch this.
The reason I want this is in the future we might break the processing of NICs and Facts in Core in similar way, so we could easily merge this. The idea is not to save anything into database during the whole import phase so plugins can hook into the process easily and at the very end of the whole processing, save all NICs and fields to database in a single place.
refs #23851
2a577f1
to
f66af61
Compare
@lzap: I moved the code as requested and adjusted tests accordingly. Regarding the "post processing framework": could you please point me to an example Hook in the Foreman code, just to get an idea of how that should look like? In case it is not tricky I could give it a try. |
I'd suggest to implement the "post processing framework" in a separate PR. It's not related to this issue. I agree it's a nice refactoring, but we don't need it now. @lzap, agreed? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, although I think better direction would be creating post-processing framework. Please document the changes in https://github.com/theforeman/theforeman.org/blob/gh-pages/plugins/foreman_discovery/nightly/index.md and we are good to merge.
I agree, luckily we can still do that later.
Here you go: theforeman/theforeman.org#1129 |
Sure, I'd rather go that direction sooner because discovery plugin is basically a collection of hacks :-) |
Thanks, @Thomas-Gelf. |
refs #23851